/* 
 * Copyright (C) 2014 Oliver Goetze
 * 
 * This file is part of Squared Battery Widget, especially made to use with buzz launcher 
 * (grid 12x10), and a 720x1280px xhdpi display. others may also work, untested...  
 * reason was, that I found no battery widget that fit my squarish needs ;) so i decided to
 * create my own widget...but from scratch is very stressy as beginner, so a cheer 
 * to free software! 
 * 
 * (many apologies for my not existent english grammar :>)
 * 
 * Squared Battery Widget is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Squared Battery Widget is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Squared Battery Widget. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package de.n3bu.squaredbatterywidget;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.os.Build;
import android.preference.PreferenceManager;
import android.widget.RemoteViews;

public class Helper {
	private final static int TRANSPARENT = R.color.transparent;
	public static final int CHARGING = 0, COLOR_100_00 = 1, COLOR_90_00 = 2,
			COLOR_80_00 = 3, COLOR_70_00 = 4, COLOR_60_00 = 5, COLOR_50_00 = 6,
			COLOR_40_00 = 7, COLOR_30_00 = 8, COLOR_20_00 = 9,
			COLOR_10_00 = 10, NOT_A_COLOR = Integer.MAX_VALUE - 132;
	public static final int TEXTCOLOR = 11;
	public static final int LAYOUT_1X1 = 12;
	public static final int LAYOUT_4X4 = 13;
	public static final int LAYOUT_RING = 14;

	public static void writeShowPercentText(Context context, boolean checked) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		SharedPreferences.Editor editor = pref.edit();
		editor.putBoolean("SBW_SHOWBATTERYTEXT", checked);
		editor.commit();
	}

	public static boolean readShowPercentText(Context context) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		return pref.getBoolean("SBW_SHOWBATTERYTEXT", true);
	}
	
	public static void writeLayout(Context context, int type) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		SharedPreferences.Editor editor = pref.edit();
		editor.putInt("SBW_LAYOUT", type);
		editor.commit();
	}

	public static int readLayout(Context context) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		return pref.getInt("SBW_LAYOUT", LAYOUT_4X4);
	}

	public static void writeColor(Context context, int type, int color) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		final SharedPreferences.Editor editor = pref.edit();
		editor.putInt("SBW_COLOROPTIONS_" + type + "_COLOR", color);
		editor.commit();
	}

	public static int readColor(Context context, int type) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);

		switch (type) {
		case CHARGING:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.white));
		case COLOR_10_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.red));
		case COLOR_20_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.darkorange));
		case COLOR_30_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.mediumorange));
		case COLOR_40_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.orange));
		case COLOR_50_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.darkyellow));
		case COLOR_60_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.mediumyellow));
		case COLOR_70_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.yellow));
		case COLOR_80_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.darkgreen));
		case COLOR_90_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.mediumgreen));
		case COLOR_100_00:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.green));
		case TEXTCOLOR:
			return pref.getInt("SBW_COLOROPTIONS_" + type + "_COLOR", context
					.getResources().getColor(R.color.white));
		default:
			return NOT_A_COLOR;
		}
	}

	public static void resetColors(Context context) {
		final SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		final SharedPreferences.Editor editor = pref.edit();
		for (int type = CHARGING; type <= TEXTCOLOR; type++) {
			editor.remove("SBW_COLOROPTIONS_" + type + "_COLOR");
		}
		editor.commit();
	}

	/*
	 * get battery level 0..100
	 */
	public static int getBatteryLevel(Intent intent) {
		return intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
	}

	/*
	 * get info wheter battery is charging
	 */
	public static boolean isBatteryCharging(Intent intent) {
		int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
		return status == BatteryManager.BATTERY_STATUS_CHARGING
				|| status == BatteryManager.BATTERY_STATUS_FULL;
	}

	public static void updateWidgets(Context c, int level, boolean isCharging) {
		final AppWidgetManager appmanager = AppWidgetManager.getInstance(c);
		final ComponentName cmpName = new ComponentName(c, SquaredBatteryWidget.class);

		int[] widgetIds = appmanager.getAppWidgetIds(cmpName);
		int color, textColor = readColor(c, TEXTCOLOR);
		boolean showPercentText = readShowPercentText(c);

		if (isCharging) {
			color = readColor(c, CHARGING);
		} else if (level < 10) {
			color = readColor(c, COLOR_10_00);
		} else if (level < 20) {
			color = readColor(c, COLOR_20_00);
		} else if (level < 30) {
			color = readColor(c, COLOR_30_00);
		} else if (level < 40) {
			color = readColor(c, COLOR_40_00);
		} else if (level < 50) {
			color = readColor(c, COLOR_50_00);
		} else if (level < 60) {
			color = readColor(c, COLOR_60_00);
		} else if (level < 70) {
			color = readColor(c, COLOR_70_00);
		} else if (level < 80) {
			color = readColor(c, COLOR_80_00);
		} else if (level < 90) {
			color = readColor(c, COLOR_90_00);
		} else {
			color = readColor(c, COLOR_100_00);
		}

		for (int wid : widgetIds) {
			RemoteViews rView = null;
			int[] tvIds = null;

			final int layout = readLayout(c);
			switch (layout) {
			case LAYOUT_1X1:
				rView = new RemoteViews(c.getPackageName(), R.layout.simple);
				if(showPercentText) {
					rView.setTextViewText(R.id.tvCenterVg, level + "");
					rView.setTextColor(R.id.tvCenterVg, textColor);
				}
				rView.setInt(R.id.tvCenterBg, "setBackgroundColor", color);
				rView.setInt(R.id.tvCenterBg, "setWidth", (int) (level * 1.2f));
				rView.setInt(R.id.tvCenterBg, "setHeight", (int) (level * 1.2f));
				break;
			case LAYOUT_RING:
				rView = new RemoteViews(c.getPackageName(), R.layout.gridlayout);
				if(showPercentText) {
					rView.setTextViewText(R.id.TextViewCenterGl, level + "");
					rView.setTextColor(R.id.TextViewCenterGl, textColor);
				}
				
				tvIds = getBatteryStateTextviewIDs(R.id.class, LAYOUT_RING);
				for (int i = 0; i < tvIds.length; i++) {
					int id = tvIds[i];
					if (i + 1 > level)
						rView.setInt(id, "setBackgroundResource", TRANSPARENT);
					else
						rView.setInt(id, "setBackgroundColor", color);
				}
				break;
			case LAYOUT_4X4:
				rView = new RemoteViews(c.getPackageName(), R.layout.main);
				if(showPercentText) {
					rView.setTextViewText(R.id.TextViewCenter, level + "");
					rView.setTextColor(R.id.TextViewCenter, textColor);
				}

				tvIds = getBatteryStateTextviewIDs(R.id.class, LAYOUT_4X4);
				for (int i = 0; i < tvIds.length; i++) {
					int id = tvIds[i];
					if ((i + 1) * 100 / 12 > level)
						rView.setInt(id, "setBackgroundResource", TRANSPARENT);
					else
						rView.setInt(id, "setBackgroundColor", color);
				}
				break;
			}
			appmanager.updateAppWidget(wid, rView);
		}
	}

	private static int[] getBatteryStateTextviewIDs(Class<?> rClass, int type)
			throws IllegalArgumentException {
		final Field[] fields = rClass.getFields();
		final Map<String, Integer> views = new HashMap<String, Integer>();
		try {
			for (int i = 0; i < fields.length; i++) {
				String fieldName = fields[i].getName();

				switch (type) {
				case LAYOUT_RING:
					if ((fields[i].getName().startsWith("tv0") && 
							!fields[i].getName().endsWith("Rl")))
						views.put(fieldName, Integer.valueOf(fields[i].getInt(null)));
					break;
				case LAYOUT_4X4:
					if ((fields[i].getName().startsWith("tv") && 
							fields[i].getName().endsWith("Rl")))
						views.put(fieldName, Integer.valueOf(fields[i].getInt(null)));
					break;
				}
			}
		} catch (Exception e) {
			throw new IllegalArgumentException();
		}

		final TreeMap<String, Integer> sortedViews = 
				new TreeMap<String, Integer>(views);
		final int[] viewIds = new int[sortedViews.size()];
		int count = 0;
		for (int id : sortedViews.values()) {
			viewIds[count++] = id;
		}
		return viewIds;
	}
}
